package hxgo

import (
	"net/http"
	"time"
	"strconv"
	"encoding/json"
	"compress/gzip"
)

// response object
type Response struct {
	Raw          http.ResponseWriter
	IsDone       bool
	IsGzip       bool
	Status       int
	Header map[string]string
	Content      string
}

// init response object with default values
func (this *Response) int() {
	this.Status = 200
	this.Header = make(map[string]string)
	this.Header["Content-Type"] = "text/html;charset=UTF-8"
	this.Header["X-Powered-By"] = "Golang"
	this.Content = ""
	this.IsGzip = false
	this.IsDone = false
}

// set cache response header
func (this *Response) Cache(ex int) {
	if ex <= 0 {
		this.Header["Cache-Control"] = "no-cache, no-store, max-age=0, must-revalidate"
		this.Header["Expires"] = "Mon, 26 Jul 1997 05:00:00 GMT"
		this.Header["Pragma"] = "no-cache"
		return
	}
	delete(this.Header, "Pragma")
	now := time.Now()
	this.Header["Last-Modified"] = now.Format(time.RFC1123)
	this.Header["Expires"] = now.Add(time.Second*time.Duration(ex)).Format(time.RFC1123)
	this.Header["Cache-Control"] = "max-age=" + strconv.Itoa(ex)
}

// set cookie header
func (this *Response) Cookie(name string, value string, expire int) {
	t := time.Now()
	t = t.Add(time.Duration(expire)*time.Second)
	cookie := &http.Cookie{
		Name:name,
		Value:value,
		Path:"/",
		MaxAge:expire,
		Expires:t,
	}
	http.SetCookie(this.Raw, cookie)
}

// response done
func (this *Response) Done() {
	if this.IsDone {
		return
	}
	for name, value := range this.Header {
		this.Raw.Header().Set(name, value)
	}
	if this.IsGzip && len(this.Content) > 0 {
		this.Raw.Header().Set("Content-Encoding", "gzip")
		g, _ := gzip.NewWriterLevel(this.Raw, gzip.BestSpeed)
		defer g.Close()
		this.Raw.WriteHeader(this.Status)
		g.Write([]byte(this.Content))
		this.IsDone = true
		return
	}
	this.Raw.WriteHeader(this.Status)
	this.Raw.Write([]byte(this.Content))
	this.IsDone = true
}

// send out redirect response
func (this *Response) Redirect(url string) {
	this.Status = 302
	this.Header["location"] = url
}

// send out error response
func (this *Response) Error(code int, cnt string) {
	this.Status = code
	this.Content = cnt
}

// send out json data response
func (this *Response) Json(data interface {}) error {
	content, err := json.Marshal(data)
	if err != nil {
		return err
	}
	this.Header["Content-Type"] = "application/json;charset=UTF-8"
	this.Content = string(content)
	return nil
}

// create new response object
func NewResponse(w http.ResponseWriter) *Response {
	res := &Response{Raw:w}
	res.int()
	return res
}
